#include "OpenglAppFramework/inc/Utils.h"
#include <sstream>

std::string getCurFileDir(const std::string& file_macro) {
    return file_macro.substr(0, file_macro.rfind('/') + 1);   
}

void genFlatPlane(float h_len, float w_len, unsigned int h_grid, unsigned int w_grid,
    float** vtx, unsigned int* vtx_cnt, int** idx, unsigned int* idx_cnt) {
    float h_step = h_len / h_grid;
    float w_step = w_len / w_grid;
    float h_start = - h_len / 2;
    float w_start = - w_len / 2;
    
    unsigned int h_vtx_cnt = h_grid + 1;
    unsigned int w_vtx_cnt = w_grid + 1;
    unsigned int out_vtx_cnt = h_vtx_cnt * w_vtx_cnt;
    unsigned int out_idx_cnt = h_grid * w_grid * 2;
    float* out_vtx = new float[out_vtx_cnt * 2];
    int * out_idx = new int[out_idx_cnt * 3];

    unsigned int buf_idx = 0;
    float w = w_start;
    float h = h_start;
    for(unsigned int i = 0; i < w_vtx_cnt; i++) {
        for(unsigned int j = 0; j < h_vtx_cnt; j++) {
            out_vtx[buf_idx++] = w;
            out_vtx[buf_idx++] = h;
            h = h_start + h_step * j;
        }
        w = w_start + w_start * i;
    }
    
    buf_idx = 0;
    for(unsigned int i = 0; i < w_grid; i++) {
        for(unsigned int j = 0; j < h_grid; j++) {
            out_idx[buf_idx++] = i * w_vtx_cnt + j;
            out_idx[buf_idx++] = (i + 1) * w_vtx_cnt + j + 1;
            out_idx[buf_idx++] = i * w_vtx_cnt + j + 1;
            out_idx[buf_idx++] = i * w_vtx_cnt + j;
            out_idx[buf_idx++] = (i + 1) * w_vtx_cnt + j;
            out_idx[buf_idx++] = (i + 1) * w_vtx_cnt + j + 1;
        }
    }
    *vtx = out_vtx;
    *idx = out_idx;
    *vtx_cnt = out_vtx_cnt;
    *idx_cnt = out_idx_cnt;
}

std::string mat2str(const glm::mat3& m) {
    std::stringstream ss;
    ss  << m[0][0] << ' ' << m[0][1] << ' ' << m[0][2] << std::endl
        << m[1][0] << ' ' << m[1][1] << ' ' << m[1][2] << std::endl
        << m[2][0] << ' ' << m[2][1] << ' ' << m[2][2] << std::endl;
    return ss.str();
}

std::string mat2str(const glm::mat4& m) {
    std::stringstream ss;
    ss  << m[0][0] << ' ' << m[0][1] << ' ' << m[0][2] << ' ' << m[0][3] << std::endl
        << m[1][0] << ' ' << m[1][1] << ' ' << m[1][2] << ' ' << m[1][3] << std::endl
        << m[2][0] << ' ' << m[2][1] << ' ' << m[2][2] << ' ' << m[2][3] << std::endl
        << m[3][0] << ' ' << m[3][1] << ' ' << m[3][2] << ' ' << m[3][3] << std::endl;
    return ss.str();
}

std::string vec2str(const glm::vec3& v) {
    std::stringstream ss;
    ss << v[0] << ' ' << v[1] << ' ' << v[2];
    return ss.str();
}
